home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / MFCINC.PAK / AFXDB.H < prev    next >
C/C++ Source or Header  |  1997-05-06  |  27KB  |  839 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1995 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #ifndef __AFXDB_H__
  12. #define __AFXDB_H__
  13.  
  14. #ifdef _AFX_NO_DB_SUPPORT
  15.     #error Database classes not supported in this library variant.
  16. #endif
  17.  
  18. #ifndef __AFXEXT_H__
  19.     #include <afxext.h>
  20. #endif
  21.  
  22. #ifndef __AFXDB__H__
  23.     #include <afxdb_.h> // shared header DAO database classes
  24. #endif
  25.  
  26. // include standard SQL/ODBC "C" APIs
  27. #ifndef __SQL
  28.     #include <sql.h>        // core
  29. #endif
  30. #ifndef __SQLEXT
  31.     #include <sqlext.h>     // extensions
  32. #endif
  33.  
  34. #ifdef _AFX_MINREBUILD
  35. #pragma component(minrebuild, off)
  36. #endif
  37. #ifndef _AFX_FULLTYPEINFO
  38. #pragma component(mintypeinfo, on)
  39. #endif
  40.  
  41. #ifndef _AFX_NOFORCE_LIBS
  42. #ifndef _MAC
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // Win32 libraries
  46.  
  47. #ifdef _AFXDLL
  48.     #if defined(_DEBUG) && !defined(_AFX_MONOLITHIC)
  49.         #ifndef _UNICODE
  50.             #pragma comment(lib, "mfcd40d.lib")
  51.         #else
  52.             #pragma comment(lib, "mfcd40ud.lib")
  53.         #endif
  54.     #endif
  55. #endif
  56.  
  57. #pragma comment(lib, "odbc32.lib")
  58. #pragma comment(lib, "odbccp32.lib")
  59.  
  60. #else //!_MAC
  61.  
  62. /////////////////////////////////////////////////////////////////////////////
  63. // Macintosh libraries
  64.  
  65. #ifdef _AFXDLL
  66.     #ifdef _DEBUG
  67.         #pragma comment(lib, "mfcd40pd.lib")
  68.     #else
  69.         #pragma comment(lib, "mfcd40p.lib")
  70.     #endif
  71. #endif
  72.  
  73. #ifdef _MPPC_
  74. #pragma comment(lib, "odbccfgp.lib")
  75. #pragma comment(lib, "odbcdrvp.lib")
  76. #else
  77. #pragma comment(lib, "odbccfgm.lib")
  78. #pragma comment(lib, "odbcdrvm.lib")
  79. #ifdef _DEBUG
  80. #pragma comment (lib, "aslmd.lib")
  81. #else
  82. #pragma comment (lib, "aslm.lib")
  83. #endif
  84. #endif
  85.  
  86. #endif //_MAC
  87. #endif //!_AFX_NOFORCE_LIBS
  88.  
  89. /////////////////////////////////////////////////////////////////////////////
  90.  
  91. #ifdef _AFX_PACKING
  92. #pragma pack(push, _AFX_PACKING)
  93. #endif
  94.  
  95. /////////////////////////////////////////////////////////////////////////////
  96. // AFXDB - MFC SQL/ODBC/Database support
  97.  
  98. // Classes declared in this file
  99.  
  100.     //CException
  101.         class CDBException;    // abnormal return value
  102.  
  103.     //CFieldExchange
  104.         class CFieldExchange;   // Recordset Field Exchange
  105.  
  106.     //CObject
  107.         class CDatabase;    // Connecting to databases
  108.         class CRecordset;   // Data result sets
  109.  
  110. //CObject
  111.     //CCmdTarget;
  112.         //CWnd
  113.             //CView
  114.                 //CScrollView
  115.                     //CFormView
  116.                         class CRecordView;     // view records with a form
  117.  
  118. // Non CObject classes
  119. struct CRecordsetStatus;
  120. struct CFieldInfo;
  121.  
  122. /////////////////////////////////////////////////////////////////////////////
  123.  
  124. // ODBC helpers
  125. // return code left in 'nRetCode'
  126. #define AFX_SQL_ASYNC(prs, SQLFunc) \
  127.     do \
  128.     { \
  129.         ASSERT(!CDatabase::InWaitForDataSource()); \
  130.         while ((nRetCode = (SQLFunc)) == SQL_STILL_EXECUTING) \
  131.             prs->OnWaitForDataSource(TRUE); \
  132.         prs->OnWaitForDataSource(FALSE); \
  133.     } while (0)
  134.  
  135. #define AFX_SQL_SYNC(SQLFunc) \
  136.     do \
  137.     { \
  138.         ASSERT(!CDatabase::InWaitForDataSource()); \
  139.         nRetCode = SQLFunc; \
  140.     } while (0)
  141.  
  142. // Max display length in chars of timestamp (date & time) value
  143. #define TIMESTAMP_PRECISION 23
  144.  
  145. // AFXDLL support
  146. #undef AFX_DATA
  147. #define AFX_DATA AFX_DB_DATA
  148.  
  149. //  Miscellaneous sizing info
  150. #define MAX_CURRENCY     30     // Max size of Currency($) string
  151. #define MAX_TNAME_LEN    64     // Max size of table names
  152. #define MAX_FNAME_LEN    64     // Max size of field names
  153. #define MAX_DBNAME_LEN   32     // Max size of a database name
  154. #define MAX_DNAME_LEN    256        // Max size of Recordset names
  155. #define MAX_CONNECT_LEN  512        // Max size of Connect string
  156. #define MAX_CURSOR_NAME  18     // Max size of a cursor name
  157.  
  158. // Timeout and net wait defaults
  159. #define DEFAULT_LOGIN_TIMEOUT 15    // seconds to before fail on connect
  160. #define DEFAULT_QUERY_TIMEOUT 15    // seconds to before fail waiting for results
  161. #define DEFAULT_MAX_WAIT_FOR_DATASOURCE 250 // milliseconds. Give DATASOURCE 1/4 second to respond
  162. #define DEFAULT_MIN_WAIT_FOR_DATASOURCE 50  // milliseconds. Start value for min wait heuristic
  163.  
  164. // Field Flags, used to indicate status of fields
  165. #define AFX_SQL_FIELD_FLAG_DIRTY    0x1
  166. #define AFX_SQL_FIELD_FLAG_NULL     0x2
  167.  
  168. // Update options flags
  169. #define AFX_SQL_SETPOSUPDATES       0x0001
  170. #define AFX_SQL_POSITIONEDSQL       0x0002
  171. #define AFX_SQL_GDBOUND             0x0004
  172.  
  173. /////////////////////////////////////////////////////////////////////////////
  174. // CDBException - something gone wrong
  175.  
  176. // Dbkit extended error codes
  177. #define AFX_SQL_ERROR                           1000
  178. #define AFX_SQL_ERROR_CONNECT_FAIL              AFX_SQL_ERROR+1
  179. #define AFX_SQL_ERROR_RECORDSET_FORWARD_ONLY    AFX_SQL_ERROR+2
  180. #define AFX_SQL_ERROR_EMPTY_COLUMN_LIST         AFX_SQL_ERROR+3
  181. #define AFX_SQL_ERROR_FIELD_SCHEMA_MISMATCH     AFX_SQL_ERROR+4
  182. #define AFX_SQL_ERROR_ILLEGAL_MODE              AFX_SQL_ERROR+5
  183. #define AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED    AFX_SQL_ERROR+6
  184. #define AFX_SQL_ERROR_NO_CURRENT_RECORD         AFX_SQL_ERROR+7
  185. #define AFX_SQL_ERROR_NO_ROWS_AFFECTED          AFX_SQL_ERROR+8
  186. #define AFX_SQL_ERROR_RECORDSET_READONLY        AFX_SQL_ERROR+9
  187. #define AFX_SQL_ERROR_SQL_NO_TOTAL              AFX_SQL_ERROR+10
  188. #define AFX_SQL_ERROR_ODBC_LOAD_FAILED          AFX_SQL_ERROR+11
  189. #define AFX_SQL_ERROR_DYNASET_NOT_SUPPORTED     AFX_SQL_ERROR+12
  190. #define AFX_SQL_ERROR_SNAPSHOT_NOT_SUPPORTED    AFX_SQL_ERROR+13
  191. #define AFX_SQL_ERROR_API_CONFORMANCE           AFX_SQL_ERROR+14
  192. #define AFX_SQL_ERROR_SQL_CONFORMANCE           AFX_SQL_ERROR+15
  193. #define AFX_SQL_ERROR_NO_DATA_FOUND             AFX_SQL_ERROR+16
  194. #define AFX_SQL_ERROR_ROW_UPDATE_NOT_SUPPORTED  AFX_SQL_ERROR+17
  195. #define AFX_SQL_ERROR_ODBC_V2_REQUIRED          AFX_SQL_ERROR+18
  196. #define AFX_SQL_ERROR_NO_POSITIONED_UPDATES     AFX_SQL_ERROR+19
  197. #define AFX_SQL_ERROR_LOCK_MODE_NOT_SUPPORTED   AFX_SQL_ERROR+20
  198. #define AFX_SQL_ERROR_DATA_TRUNCATED            AFX_SQL_ERROR+21
  199. #define AFX_SQL_ERROR_ROW_FETCH                 AFX_SQL_ERROR+22
  200. #define AFX_SQL_ERROR_INCORRECT_ODBC            AFX_SQL_ERROR+23
  201. #define AFX_SQL_ERROR_UPDATE_DELETE_FAILED      AFX_SQL_ERROR+24
  202. #define AFX_SQL_ERROR_DYNAMIC_CURSOR_NOT_SUPPORTED  AFX_SQL_ERROR+25
  203. #define AFX_SQL_ERROR_MAX                       AFX_SQL_ERROR+26
  204.  
  205. class CDBException : public CException
  206. {
  207.     DECLARE_DYNAMIC(CDBException)
  208.  
  209. // Attributes
  210. public:
  211.     RETCODE m_nRetCode;
  212.     CString m_strError;
  213.     CString m_strStateNativeOrigin;
  214.  
  215. // Implementation (use AfxThrowDBException to create)
  216. public:
  217.     CDBException(RETCODE nRetCode = SQL_SUCCESS);
  218.  
  219.     virtual void BuildErrorString(CDatabase* pdb, HSTMT hstmt,
  220.         BOOL bTrace = TRUE);
  221.     void Empty();
  222.     virtual ~CDBException();
  223.  
  224.     virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  225.         PUINT pnHelpContext = NULL);
  226.  
  227. #ifdef _DEBUG
  228.     void TraceErrorMessage(LPCTSTR szTrace) const;
  229. #endif // DEBUG
  230.  
  231. };
  232.  
  233. void AFXAPI AfxThrowDBException(RETCODE nRetCode, CDatabase* pdb, HSTMT hstmt);
  234.  
  235. //////////////////////////////////////////////////////////////////////////////
  236. // CDatabase - a SQL Database
  237.  
  238. class CDatabase : public CObject
  239. {
  240.     DECLARE_DYNAMIC(CDatabase)
  241.  
  242. // Constructors
  243. public:
  244.     CDatabase();
  245.  
  246.     virtual BOOL Open(LPCTSTR lpszDSN, BOOL bExclusive = FALSE,
  247.         BOOL bReadonly = FALSE, LPCTSTR lpszConnect = _T("ODBC;"),
  248.         BOOL bUseCursorLib = TRUE);
  249.     virtual void Close();
  250.  
  251. // Attributes
  252. public:
  253.     HDBC m_hdbc;
  254.  
  255.     BOOL IsOpen() const;        // Database successfully opened?
  256.     BOOL CanUpdate() const;
  257.     BOOL CanTransact() const;   // Are Transactions supported?
  258.  
  259.     CString GetDatabaseName() const;
  260.     const CString& GetConnect() const;
  261.  
  262.     // global state - if waiting for datasource => not normal operations
  263.     static BOOL PASCAL InWaitForDataSource();
  264.  
  265. // Operations
  266. public:
  267.     void SetLoginTimeout(DWORD dwSeconds);
  268.     void SetQueryTimeout(DWORD dwSeconds);
  269.     void SetSynchronousMode(BOOL bSynchronous);
  270.  
  271.     // transaction control
  272.     BOOL BeginTrans();
  273.     BOOL CommitTrans();
  274.     BOOL Rollback();
  275.  
  276.     // direct sql execution
  277.     void ExecuteSQL(LPCTSTR lpszSQL);
  278.  
  279.     // Cancel asynchronous operation
  280.     void Cancel();
  281.  
  282. // Overridables
  283. public:
  284.     // set special options
  285.     virtual void OnSetOptions(HSTMT hstmt);
  286.  
  287.     // Give user chance to cancel long operation
  288.     virtual void OnWaitForDataSource(BOOL bStillExecuting);
  289.  
  290. // Implementation
  291. public:
  292.     virtual ~CDatabase();
  293.  
  294. #ifdef _DEBUG
  295.     virtual void AssertValid() const;
  296.     virtual void Dump(CDumpContext& dc) const;
  297.  
  298.     BOOL m_bTransactionPending;
  299. #endif //_DEBUG
  300.  
  301.     // general error check
  302.     virtual BOOL Check(RETCODE nRetCode) const;
  303.  
  304.     void ReplaceBrackets(LPTSTR lpchSQL);
  305.     BOOL m_bStripTrailingSpaces;
  306.     BOOL m_bIncRecordCountOnAdd;
  307.  
  308. protected:
  309.     CString m_strConnect;
  310.  
  311.     CPtrList m_listRecordsets;  // maintain list to ensure CRecordsets all closed
  312.  
  313.     int nRefCount;
  314.     BOOL m_bUpdatable;
  315.  
  316.     BOOL m_bTransactions;
  317.     SWORD m_nTransactionCapable;
  318.     SWORD m_nCursorCommitBehavior;
  319.     SWORD m_nCursorRollbackBehavior;
  320.     DWORD m_dwUpdateOptions;
  321.  
  322.     DWORD m_dwLoginTimeout;
  323.     HSTMT m_hstmt;
  324.     DWORD m_dwWait;
  325.  
  326.     DWORD m_dwQueryTimeout;
  327.     DWORD m_dwMinWaitForDataSource;
  328.     DWORD m_dwMaxWaitForDataSource;
  329.     BOOL m_bAsync;
  330.     char m_chIDQuoteChar;
  331.     char m_reserved1[3];        // pad to even 4 bytes
  332.  
  333.     virtual void ThrowDBException(RETCODE nRetCode);
  334.     void AllocConnect();
  335.     void Free();
  336.  
  337.     // friend classes that call protected CDatabase overridables
  338.     friend class CRecordset;
  339.     friend class CFieldExchange;
  340.     friend class CDBException;
  341. };
  342.  
  343. // CFieldExchange - for field exchange
  344. class CFieldExchange
  345. {
  346. // Attributes
  347. public:
  348.     enum RFX_Operation
  349.     {
  350.         BindParam, // register users parameters with ODBC SQLBindParameter
  351.         RebindParam, //  migrate param values to proxy array before Requery
  352.         BindFieldToColumn, // register users fields with ODBC SQLBindCol
  353.         BindFieldForUpdate, // temporarily bind columns before update (via SQLSetPos)
  354.         UnbindFieldForUpdate, // unbind columns after update (via SQLSetPos)
  355.         Fixup, // Set string lengths, clear status bits
  356.         MarkForAddNew,
  357.         MarkForUpdate,  // Prepare fields and flags for update operation
  358.         Name, // append dirty field name
  359.         NameValue, // append dirty name=value
  360.         Value, // append dirty value or parameter marker
  361.         SetFieldDirty, // Set status bit for changed status
  362.         SetFieldNull,   // Set status bit for null value
  363.         IsFieldDirty,// return TRUE if field is dirty
  364.         IsFieldNull,// return TRUE if field is marked NULL
  365.         IsFieldNullable,// return TRUE if field can hold NULL values
  366.         StoreField, // archive values of current record
  367.         LoadField,  // reload archived values into current record
  368.         GetFieldInfoValue,  // general info on a field via pv for field
  369.         GetFieldInfoOrdinal,    // general info on a field via field ordinal
  370. #ifdef _DEBUG
  371.         DumpField,  // dump bound field name and value
  372. #endif
  373.     };
  374.     UINT m_nOperation;  // Type of exchange operation
  375.     CRecordset* m_prs;  // recordset handle
  376.  
  377. // Operations
  378.     enum FieldType
  379.     {
  380.         noFieldType,
  381.         outputColumn,
  382.         param,
  383.     };
  384.  
  385. // Operations (for implementors of RFX procs)
  386.     BOOL IsFieldType(UINT* pnField);
  387.  
  388.     // Indicate purpose of subsequent RFX calls
  389.     void SetFieldType(UINT nFieldType);
  390.  
  391. // Implementation
  392.     CFieldExchange(UINT nOperation, CRecordset* prs, void* pvField = NULL);
  393.  
  394.     void Default(LPCTSTR szName,
  395.         void* pv, LONG* plLength, int nCType, UINT cbValue, UINT cbPrecision);
  396.  
  397.     int GetColumnType(int nColumn, UINT* pcbLength = NULL,
  398.         int* pnScale = NULL, int* pnNullable = NULL);
  399.  
  400.     // long binary helpers
  401.     long GetLongBinarySize(int nField);
  402.     void GetLongBinaryData(int nField, CLongBinary& lb, long* plSize);
  403.     BYTE* ReallocLongBinary(CLongBinary& lb, long lSizeRequired,
  404.         long lReallocSize);
  405.  
  406.     // Current type of field
  407.     UINT m_nFieldType;
  408.  
  409.     // For GetFieldInfo
  410.     CFieldInfo* m_pfi;  // GetFieldInfo return struct
  411.     BOOL m_bFieldFound; // GetFieldInfo search successful
  412.  
  413.     // For returning status info for a field
  414.     BOOL m_bNull;       // return result of IsFieldNull(able)/Dirty operation
  415.     BOOL m_bDirty;      // return result of IsFieldNull(able)/Dirty operation
  416.  
  417.     CString* m_pstr;    // Field name or destination for building various SQL clauses
  418.     BOOL m_bField;      // Value to set for SetField operation
  419.     void* m_pvField;    // For indicating an operation on a specific field
  420.     CArchive* m_par;    // For storing/loading copy buffer
  421.     LPCTSTR m_lpszSeparator; // append after field names
  422.     UINT m_nFields;     // count of fields for various operations
  423.     UINT m_nParams;     // count of fields for various operations
  424.     UINT m_nParamFields;    // count of fields for various operations
  425.     HSTMT m_hstmt;      // For SQLBindParameter on update statement
  426.     long m_lDefaultLBFetchSize;     // For fetching CLongBinary data of unknown len
  427.     long m_lDefaultLBReallocSize;   // For fetching CLongBinary data of unknown len
  428.  
  429. #ifdef _DEBUG
  430.     CDumpContext* m_pdcDump;
  431. #endif //_DEBUG
  432.  
  433. };
  434.  
  435. /////////////////////////////////////////////////////////////////////////////
  436. // Standard RecordSet Field Exchange routines
  437.  
  438. // text data
  439. void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, CString& value,
  440.     // Default max length for char and varchar, default datasource type
  441.     int nMaxLength = 255, int nColumnType = SQL_VARCHAR);
  442.  
  443. // boolean data
  444. void AFXAPI RFX_Bool(CFieldExchange* pFX, LPCTSTR szName, BOOL& value);
  445.  
  446. // integer data
  447. void AFXAPI RFX_Long(CFieldExchange* pFX, LPCTSTR szName, long& value);
  448. void AFXAPI RFX_Int(CFieldExchange* pFX, LPCTSTR szName, int& value);
  449. void AFXAPI RFX_Single(CFieldExchange* pFX, LPCTSTR szName, float& value);
  450. void AFXAPI RFX_Double(CFieldExchange* pFX, LPCTSTR szName, double& value);
  451.  
  452. // date and time
  453. void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, CTime& value);
  454. void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, TIMESTAMP_STRUCT& value);
  455.  
  456. // Binary data
  457. void AFXAPI RFX_Binary(CFieldExchange* pFX, LPCTSTR szName, CByteArray& value,
  458.     // Default max length is for binary and varbinary
  459.     int nMaxLength = 255);
  460. void AFXAPI RFX_Byte(CFieldExchange* pFX, LPCTSTR szName, BYTE& value);
  461. void AFXAPI RFX_LongBinary(CFieldExchange* pFX, LPCTSTR szName, CLongBinary& value);
  462.  
  463. /////////////////////////////////////////////////////////////////////////////
  464. // Database Dialog Data Exchange cover routines
  465. // Cover routines provide database semantics on top of DDX routines
  466.  
  467. // simple text operations
  468. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, BYTE& value, CRecordset* pRecordset);
  469. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
  470. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, UINT& value, CRecordset* pRecordset);
  471. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, long& value, CRecordset* pRecordset);
  472. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, DWORD& value, CRecordset* pRecordset);
  473. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
  474. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, double& value, CRecordset* pRecordset);
  475. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, float& value, CRecordset* pRecordset);
  476.  
  477. // special control types
  478. void AFXAPI DDX_FieldCheck(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
  479. void AFXAPI DDX_FieldRadio(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
  480. void AFXAPI DDX_FieldLBString(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
  481. void AFXAPI DDX_FieldCBString(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
  482. void AFXAPI DDX_FieldLBIndex(CDataExchange* pDX, int nIDC, int& index, CRecordset* pRecordset);
  483. void AFXAPI DDX_FieldCBIndex(CDataExchange* pDX, int nIDC, int& index, CRecordset* pRecordset);
  484. void AFXAPI DDX_FieldLBStringExact(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
  485. void AFXAPI DDX_FieldCBStringExact(CDataExchange* pDX, int nIDC, CString& value, CRecordset* pRecordset);
  486. void AFXAPI DDX_FieldScroll(CDataExchange* pDX, int nIDC, int& value, CRecordset* pRecordset);
  487.  
  488. //////////////////////////////////////////////////////////////////////////////
  489. // CRecordset - the result of a SQL Statement
  490.  
  491. #define AFX_DB_USE_DEFAULT_TYPE     (0xFFFFFFFF)
  492.  
  493. #define AFX_MOVE_FIRST      0x80000000L
  494. #define AFX_MOVE_PREVIOUS   (-1L)
  495. #define AFX_MOVE_REFRESH    0L
  496. #define AFX_MOVE_NEXT       (+1L)
  497. #define AFX_MOVE_LAST       0x7fffffffL
  498.  
  499. #define AFX_RECORDSET_STATUS_OPEN    (+1L)
  500. #define AFX_RECORDSET_STATUS_CLOSED  0L
  501. #define AFX_RECORDSET_STATUS_UNKNOWN (-1L)
  502.  
  503. class CRecordset : public CObject
  504. {
  505.     DECLARE_DYNAMIC(CRecordset)
  506.  
  507. // Constructor
  508. protected:
  509.     CRecordset(CDatabase* pDatabase = NULL);
  510.  
  511. public:
  512.     virtual ~CRecordset();
  513.  
  514.     enum OpenType
  515.     {
  516.         dynaset,        // uses SQLExtendedFetch, keyset driven cursor
  517.         snapshot,       // uses SQLExtendedFetch, static cursor
  518.         forwardOnly,    // uses SQLFetch
  519.         dynamic         // uses SQLExtendedFetch, dynamic cursor
  520.     };
  521.  
  522.     enum OpenOptions
  523.     {
  524.         none =          0x0,
  525.         readOnly =      0x0004,
  526.         appendOnly =        0x0008,
  527.         optimizeBulkAdd =   0x4000, // Use prepared HSTMT for multiple AddNews, dirty fields must not change.
  528.         firstBulkAdd =      0x8000, // INTERNAL to MFC, don't specify on Open.
  529.     };
  530.     virtual BOOL Open(UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
  531.         LPCTSTR lpszSQL = NULL, DWORD dwOptions = none);
  532.     virtual void Close();
  533.  
  534. // Attributes
  535. public:
  536.     HSTMT m_hstmt;          // Source statement for this resultset
  537.     CDatabase* m_pDatabase;       // Source database for this resultset
  538.  
  539.     CString m_strFilter;        // Where clause
  540.     CString m_strSort;      // Order By Clause
  541.  
  542.     BOOL CanAppend() const;     // Can AddNew be called?
  543.     BOOL CanRestart() const;    // Can Requery be called to restart a query?
  544.     BOOL CanScroll() const;     // Can MovePrev and MoveFirst be called?
  545.     BOOL CanTransact() const;   // Are Transactions supported?
  546.     BOOL CanUpdate() const;     // Can Edit/AddNew/Delete be called?
  547.  
  548.     const CString& GetSQL() const;      // SQL executed for this recordset
  549.     const CString& GetTableName() const;        // Table name
  550.  
  551.     BOOL IsOpen() const;        // Recordset successfully opened?
  552.     BOOL IsBOF() const;     // Beginning Of File
  553.     BOOL IsEOF() const;     // End Of File
  554.     BOOL IsDeleted() const;     // On a deleted record
  555.  
  556.     BOOL IsFieldDirty(void *pv);    // has field been updated?
  557.     BOOL IsFieldNull(void *pv); // is field NULL valued?
  558.     BOOL IsFieldNullable(void *pv); // can field be set to a NULL value
  559.  
  560.     long GetRecordCount() const;        // Records seen so far or -1 if unknown
  561.     void GetStatus(CRecordsetStatus& rStatus) const;
  562.  
  563. // Operations
  564. public:
  565.     // cursor operations
  566.     void MoveNext();
  567.     void MovePrev();
  568.     void MoveFirst();
  569.     void MoveLast();
  570.     virtual void Move(long lRows);
  571.  
  572.     // edit buffer operations
  573.     virtual void AddNew();      // add new record at the end
  574.     virtual void Edit();        // start editing
  575.     virtual BOOL Update();      // update it
  576.     virtual void Delete();      // delete the current record
  577.  
  578.     // field operations
  579.     void SetFieldDirty(void *pv, BOOL bDirty = TRUE);
  580.     void SetFieldNull(void *pv, BOOL bNull = TRUE);
  581.  
  582.     // locking control during Edit
  583.     enum LockMode
  584.     {
  585.         optimistic,
  586.         pessimistic,
  587.     };
  588.     void SetLockingMode(UINT nMode);
  589.  
  590.     // Recordset operations
  591.     virtual BOOL Requery();         // Re-execute query based on new params
  592.  
  593.     // Cancel asynchronous operation
  594.     void Cancel();
  595.  
  596. // Overridables
  597. public:
  598.     // Get default connect string
  599.     virtual CString GetDefaultConnect();
  600.  
  601.     // Get SQL to execute
  602.     virtual CString GetDefaultSQL() = 0;
  603.  
  604.     // set special options
  605.     virtual void OnSetOptions(HSTMT hstmt);
  606.  
  607.     // Give user chance to cancel long operation
  608.     virtual void OnWaitForDataSource(BOOL bStillExecuting);
  609.  
  610.     // for recordset field exchange
  611.     virtual void DoFieldExchange(CFieldExchange* pFX) = 0;
  612.  
  613. // Implementation
  614. public:
  615. #ifdef _DEBUG
  616.     virtual void AssertValid() const;
  617.     virtual void Dump(CDumpContext& dc) const;
  618. #endif //_DEBUG
  619.  
  620.     virtual BOOL Check(RETCODE nRetCode) const; // general error check
  621.     void InitRecord();
  622.     virtual void PreBindFields();   // called before data fields are bound
  623.     UINT m_nFields;         // number of RFX fields
  624.     UINT m_nParams;         // number of RFX params
  625.     BOOL m_bRebindParams;     // date or UNICODE text parameter existence flag
  626.     BOOL m_bLongBinaryColumns;  // long binary column existence flag
  627.     BOOL m_bUseUpdateSQL;   // uses SQL-based updates
  628.     int m_nReserved;    // reserved for later use
  629.     BOOL m_bUseODBCCursorLib;   // uses ODBC cursor lib if m_pDatabase not Open
  630.     UDWORD m_dwDriverPositionedStatements;
  631.  
  632.     BOOL IsSQLUpdatable(LPCTSTR lpszSQL);
  633.     BOOL IsSelectQueryUpdatable(LPCTSTR lpszSQL);
  634.     static BOOL PASCAL IsJoin(LPCTSTR lpszJoinClause);
  635.     static LPCTSTR PASCAL FindSQLToken(LPCTSTR lpszSQL, LPCTSTR lpszSQLToken);
  636.     BOOL ValidateSelectForUpdateSupport();
  637.  
  638.     // RFX Operations on fields of CRecordset
  639.     UINT BindParams(HSTMT hstmt);
  640.     void RebindParams(HSTMT hstmt);
  641.     UINT BindFieldsToColumns();
  642.     void BindFieldsForUpdate();
  643.     void UnbindFieldsForUpdate();
  644.     void Fixups();
  645.     UINT AppendNames(CString* pstr, LPCTSTR szSeparator);
  646.     UINT AppendValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
  647.     UINT AppendNamesValues(HSTMT hstmt, CString* pstr, LPCTSTR szSeparator);
  648.     void StoreFields();
  649.     void LoadFields();
  650.     void MarkForAddNew();
  651.     void MarkForUpdate();
  652.     BOOL GetFieldInfo(void* pv, CFieldInfo* pfi);
  653.     BOOL GetFieldInfo(UINT nField, CFieldInfo* pfi);
  654. #ifdef _DEBUG
  655.     void DumpFields(CDumpContext& dc) const;
  656. #endif //_DEBUG
  657.  
  658.     // RFX operation helper functions
  659.     BOOL UnboundFieldInfo(UINT nField, CFieldInfo* pfi);
  660.  
  661.     virtual void ThrowDBException(RETCODE nRetCode, HSTMT hstmt = SQL_NULL_HSTMT);
  662.  
  663.     CMemFile* m_pmemfile;   // For saving copy buffer
  664.     CArchive* m_par;    // For saving copy buffer
  665.  
  666.     void AllocFlags();
  667.     BYTE GetFieldFlags(UINT nField, UINT nFieldType = CFieldExchange::outputColumn);
  668.     void SetFieldFlags(UINT nField, BYTE bFlags, UINT nFieldType = CFieldExchange::outputColumn);
  669.     void ClearFieldFlags(UINT nField, BYTE bFlags, UINT nFieldType = CFieldExchange::outputColumn);
  670.     LONG* GetFieldLength(CFieldExchange* pFX);
  671.     BOOL IsFieldFlagNull(UINT nField, UINT nFieldType);
  672.     BOOL IsFieldFlagDirty(UINT nField, UINT nFieldType);
  673.     void** m_pvFieldProxy;
  674.     void** m_pvParamProxy;
  675.     UINT m_nProxyFields;
  676.     UINT m_nProxyParams;
  677.  
  678. protected:
  679.     UINT m_nOpenType;
  680.     UINT m_nDefaultType;
  681.     enum EditMode
  682.     {
  683.         noMode,
  684.         edit,
  685.         addnew
  686.     };
  687.     long m_lOpen;
  688.     UINT m_nEditMode;
  689.     BOOL m_bEOFSeen;
  690.     long m_lRecordCount;
  691.     long m_lCurrentRecord;
  692.     CString m_strCursorName;
  693.     // Perform operation based on m_nEditMode
  694.     BOOL UpdateInsertDelete();
  695.     void ReleaseCopyBuffer();
  696.     BOOL m_nLockMode;       // Control concurrency for Edit()
  697.     UDWORD m_dwDriverConcurrency;   // driver supported concurrency types
  698.     UDWORD m_dwConcurrency; // requested concurrency type
  699.     UWORD m_wRowStatus;     // row status used by SQLExtendedFetch and SQLSetPos
  700.     HSTMT m_hstmtUpdate;
  701.     BOOL m_bRecordsetDb;
  702.     BOOL m_bBOF;
  703.     BOOL m_bEOF;
  704.     BOOL m_bUpdatable;      // Is recordset updatable?
  705.     BOOL m_bAppendable;
  706.     CString m_strSQL;       // SQL statement for recordset
  707.     CString m_strUpdateSQL; // SQL statement for updates
  708.     CString m_strTableName;     // source table of recordset
  709.     BOOL m_bScrollable; // supports MovePrev
  710.     BOOL m_bDeleted;
  711.     DWORD m_dwWait;
  712.     UINT m_nFieldsBound;
  713.     BYTE* m_pbFieldFlags;
  714.     LONG* m_plFieldLength;  // Pointer to field length bound in SQLBindCol
  715.     BYTE* m_pbParamFlags;
  716.     LONG* m_plParamLength;
  717.     BOOL m_bExtendedFetch;
  718. public:
  719.     DWORD m_dwOptions;          // archive dwOptions on Open
  720. protected:
  721.     CString m_strRequerySQL;    // archive SQL string for use in Requery()
  722.     CString m_strRequeryFilter; // archive filter string for use in Requery()
  723.     CString m_strRequerySort;   // archive sort string for use in Requery()
  724.     void BuildSelectSQL();
  725.     void AppendFilterAndSortSQL();
  726.     BOOL IsRecordsetUpdatable();
  727.     void ExecuteSetPosUpdate();
  728.     void PrepareUpdateHstmt();
  729.     void BuildUpdateSQL();
  730.     void ExecuteUpdateSQL();
  731.     void SendLongBinaryData(HSTMT hstmt);
  732.     virtual long GetLBFetchSize(long lOldSize);     // CLongBinary fetch chunking
  733.     virtual long GetLBReallocSize(long lOldSize);   // CLongBinary realloc chunking
  734.  
  735.     friend class CFieldExchange;
  736.     friend class CRecordView;
  737. };
  738.  
  739. #define AFX_CURRENT_RECORD_UNDEFINED (-2)
  740. #define AFX_CURRENT_RECORD_BOF (-1)
  741.  
  742. // For returning status for a recordset
  743. struct CRecordsetStatus
  744. {
  745.     long m_lCurrentRecord;  // -2=Unknown,-1=BOF,0=1st record. . .
  746.     BOOL m_bRecordCountFinal;// Have we counted all records?
  747. };
  748.  
  749. // For returning field info on RFX fields
  750. struct CFieldInfo
  751. {
  752.     // For ID'ing field
  753.     UINT nField;        // Field number
  754.     CString strName;    // Field name
  755.     void* pv;       // Address of value for field
  756.  
  757.     // Return info GetFieldInfo
  758.     UINT nDataType;     // data type of field (BOOL, BYTE, etc)
  759.     DWORD dwSize;       // Max size for field data
  760. };
  761.  
  762. /////////////////////////////////////////////////////////////////////////////
  763. // CRecordView - form for viewing data records
  764.  
  765. class CRecordView : public CFormView
  766. {
  767.     DECLARE_DYNAMIC(CRecordView)
  768.  
  769. // Construction
  770. protected:  // must derive your own class
  771.     CRecordView(LPCTSTR lpszTemplateName);
  772.     CRecordView(UINT nIDTemplate);
  773.  
  774. // Attributes
  775. public:
  776.     virtual CRecordset* OnGetRecordset() = 0;
  777.  
  778.     BOOL IsOnLastRecord();
  779.     BOOL IsOnFirstRecord();
  780.  
  781. // Operations
  782. public:
  783.     virtual BOOL OnMove(UINT nIDMoveCommand);
  784.  
  785. // Implementation
  786. public:
  787.     virtual ~CRecordView();
  788. #ifdef _DEBUG
  789.     virtual void AssertValid() const;
  790.     virtual void Dump(CDumpContext& dc) const;
  791. #endif
  792.     virtual void OnInitialUpdate();
  793.  
  794. protected:
  795.     BOOL m_bOnFirstRecord;
  796.     BOOL m_bOnLastRecord;
  797.  
  798.     //{{AFX_MSG(CRecordView)
  799.     afx_msg void OnUpdateRecordFirst(CCmdUI* pCmdUI);
  800.     afx_msg void OnUpdateRecordPrev(CCmdUI* pCmdUI);
  801.     afx_msg void OnUpdateRecordNext(CCmdUI* pCmdUI);
  802.     afx_msg void OnUpdateRecordLast(CCmdUI* pCmdUI);
  803.     //}}AFX_MSG
  804.     afx_msg void OnMove(int cx, int cy);
  805.  
  806.     DECLARE_MESSAGE_MAP()
  807. };
  808.  
  809. /////////////////////////////////////////////////////////////////////////////
  810. // Inline function declarations
  811.  
  812. #ifdef _AFX_PACKING
  813. #pragma pack(pop)
  814. #endif
  815.  
  816. #ifdef _AFX_ENABLE_INLINES
  817. #define _AFXDBCORE_INLINE inline
  818. #define _AFXDBRFX_INLINE inline
  819. #define _AFXDBVIEW_INLINE inline
  820. #include <afxdb.inl>
  821. #undef _AFXDBVIEW_INLINE
  822. #undef _AFXDBCORE_INLINE
  823. #undef _AFXDBRFX_INLINE
  824. #endif
  825.  
  826. #undef AFX_DATA
  827. #define AFX_DATA
  828.  
  829. #ifdef _AFX_MINREBUILD
  830. #pragma component(minrebuild, on)
  831. #endif
  832. #ifndef _AFX_FULLTYPEINFO
  833. #pragma component(mintypeinfo, off)
  834. #endif
  835.  
  836. #endif //__AFXDB_H__
  837.  
  838. /////////////////////////////////////////////////////////////////////////////
  839.